
package mitm;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;


public abstract class ProxyEngine implements Runnable {

	public static final String ACCEPT_TIMEOUT_MESSAGE = "Listen time out";
	
	private final ProxyDataFilter m_requestFilter;
	private final ProxyDataFilter m_responseFilter;
	private final ConnectionDetails m_connectionDetails;

	private final PrintWriter m_outputWriter;

	public final MITMSocketFactory m_socketFactory;
	protected ServerSocket m_serverSocket;

	public ProxyEngine(MITMSocketFactory socketFactory, ProxyDataFilter requestFilter, ProxyDataFilter responseFilter, 
			ConnectionDetails connectionDetails, int timeout) throws IOException {
		
		m_socketFactory = socketFactory;
		m_requestFilter = requestFilter;
		m_responseFilter = responseFilter;
		m_connectionDetails = connectionDetails;

		m_outputWriter = requestFilter.getOutputPrintWriter();

		m_serverSocket = m_socketFactory.createServerSocket(connectionDetails.getLocalHost(), connectionDetails.getLocalPort(), timeout);
	}

	public final ServerSocket getServerSocket() {
		return m_serverSocket;
	}

	protected final MITMSocketFactory getSocketFactory() {
		return m_socketFactory;
	}

	protected final ConnectionDetails getConnectionDetails() {
		return m_connectionDetails;
	}

	/*
	 * Launch a pair of threads that: (1) Copy data sent from the client to the
	 * remote server (2) Copy data sent from the remote server to the client
	 */
	
	protected final void launchThreadPair(Socket localSocket, Socket remoteSocket, InputStream localInputStream,
			OutputStream localOutputStream, String remoteHost, int remotePort) throws IOException {

		new StreamThread(new ConnectionDetails(m_connectionDetails.getLocalHost(), localSocket.getPort(),
				remoteHost, remoteSocket.getPort(), m_connectionDetails.isSecure()), localInputStream,
				remoteSocket.getOutputStream(), m_requestFilter, m_outputWriter);

		new StreamThread(new ConnectionDetails(remoteHost, remoteSocket.getPort(), m_connectionDetails.getLocalHost(),
				localSocket.getPort(), m_connectionDetails.isSecure()), remoteSocket.getInputStream(), localOutputStream,
				m_responseFilter, m_outputWriter);
	}
}